import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import javafx.scene.paint.Color;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.swing.Timer;

// 继承 JFrame 为了直接复用swing框架中窗口管理的能力
// 为了子类可以直接调用 JFrame public 的方法

// ActionListener 是java中事件处理机制的核心部分
// 为了建立计算器组件和用户操作之间的响应机制
public class Calculator extends JFrame implements ActionListener {
    // 声明界面组件
    // 上下两个容器面板 文本框区域 按钮区域
    private JPanel north, center;
    // 文本框 显示计算过程、结果或者日期时间
    private JTextField field;
    // 按钮
    private JButton[] btns;
    // 播放音乐 停止音乐按钮
    private Clip backgroundMusic;
    private JButton playMusicBtn, stopMusicBtn;

    // 新增时间相关变量
    private Timer timeTimer; // 更新时间显示的定时器
    private boolean isTimeDisplaying = false;// 是否正在显示时间
    private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");// 时间格式

    // 初始化窗口 - 构造器 构造方法 无参构造器
    public Calculator() {
        // 设置窗口title
        setTitle("计算器");
        // 设置窗口大小
        setSize(700, 700);
        // 设置窗口关闭时程序
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 设置窗口居中显示
        setLocationRelativeTo(null);

        // 初始化音乐
        initMusic();

        // 初始化界面组件
        initComponent();
        // 设置窗口显示
        setVisible(true);
    }

    // 初始化音乐
    private void initMusic() {
        try {
            // 从文件加载音频
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(
                    new File("background_music.wav")); // 需要提供音乐文件
            // 获取音频 打开音频
            backgroundMusic = AudioSystem.getClip();
            backgroundMusic.open(audioInputStream);
            // 设置循环播放
            backgroundMusic.loop(Clip.LOOP_CONTINUOUSLY);
            backgroundMusic.stop(); // 默认不播放
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "无法加载背景音乐", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    // 初始化界面组件
    private void initComponent() {

        // 设置窗口背景色
        // getContentPane().setBackground(Color(230, 230, 250)); // 淡紫色背景

        // System.out.println("initComponent");
        // 创建面板容器
        // 容器面板 文本框区域
        north = new JPanel();
        // 容器面板 按钮区域
        center = new JPanel();

        // 音乐按钮区域
        JPanel south = new JPanel(); // 新增底部面板用于音乐控制按钮

        // 文本框 显示计算过程、结果或者日期时间
        field = new JTextField();

        field.setPreferredSize(new Dimension(700, 150));
        // 禁用文字输入 禁止通过电脑键盘输入编辑
        field.setEditable(false);
        // 设置输入框文字大小
        field.setFont(new Font("SansSerif", Font.BOLD, 25));

        // 仅添加输入框颜色设置
        field.setBackground(new java.awt.Color(230, 210, 250)); // 紫色背景

        field.setForeground(java.awt.Color.GREEN); // 设置黑色文字

        // 按钮
        // private
        String[] str = new String[] {
                "7", "8", "9", "+",
                "4", "5", "6", "-",
                "1", "2", "3", "×",
                "0", ".", "=", "÷",
                "C", "B", "T", "S"
        };

        btns = new JButton[str.length];
        for (int i = 0; i < btns.length; i++) {
            // 设置按钮样式
            btns[i] = new JButton(str[i]);
            btns[i].setFont(new Font("SansSerif", Font.BOLD, 25));
            btns[i].setForeground(java.awt.Color.BLACK); // 新增：设置按钮文字颜色

            // 设置按钮背景颜色 - 这里使用了不同的颜色方案
            // 为不同功能的按钮设置不同颜色，提高辨识度
            if (str[i].matches("[0-9.]")) {
                // // 数字按钮 - 浅蓝色
                btns[i].setBackground(new java.awt.Color(220, 230, 241));
            } else if (str[i].matches("[+\\-×÷]")) {
                // // 运算符按钮 - 浅橙色
                btns[i].setBackground(new java.awt.Color(255, 200, 120));
            } else if (str[i].equals("=")) {
                // // 等于号按钮 - 浅绿色
                btns[i].setBackground(new java.awt.Color(220, 241, 220));
            } else {
                // // 功能按钮(C,B,T,S) - 浅粉色
                btns[i].setBackground(new java.awt.Color(241, 220, 230));
            }

        }

        // 创建音乐控制按钮
        playMusicBtn = new JButton("播放音乐");
        playMusicBtn.setFont(new Font("SansSerif", Font.BOLD, 16));
        playMusicBtn.setBackground(new java.awt.Color(200, 255, 200)); // 浅绿色
        playMusicBtn.addActionListener(e -> playMusic());

        stopMusicBtn = new JButton("停止音乐");
        stopMusicBtn.setFont(new Font("SansSerif", Font.BOLD, 16));
        stopMusicBtn.setBackground(new java.awt.Color(255, 200, 200)); // 浅红色
        stopMusicBtn.addActionListener(e -> stopMusic());
        stopMusicBtn.setEnabled(false); // 初始时停止按钮禁用

        // 将组件放到窗口中
        // 设置布局管理器
        // north 顶部面板 使用 BorderLayout 边界布局
        north.setLayout(new BorderLayout());

        center.setLayout(new GridLayout(5, 4, 5, 5)); // 添加网格间距
        // 按钮水平居中对齐
        south.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));

        // center 中间面板 使用 网格布局
        center.setLayout(new GridLayout(5, 4));
        // 组件设置
        // field 文本框 添加到 north 顶部面板 使用 BorderLayout 居中
        north.add(field, BorderLayout.CENTER);
        // 将开始播放和结束播放添加到面板
        south.add(playMusicBtn);
        south.add(stopMusicBtn);

        // 按钮添加到center面板
        // 将 north 顶部面板 添加到窗口中
        add(north, BorderLayout.NORTH);
        add(center);

        add(south, BorderLayout.SOUTH); // 添加到底部面板

        for (JButton btn : btns) {
            center.add(btn); // 通过遍历将所有按钮添加到center面板

        }

        // 绑定按钮监听事件
        for (JButton btn : btns) {
            btn.addActionListener(this);
        }
        // 初始化时间定时器（但不启动）
        timeTimer = new Timer(1000, e -> {
            field.setText(LocalTime.now().format(timeFormatter));
        });

    }

    // 播放音乐
    private void playMusic() {
        if (backgroundMusic != null) {
            backgroundMusic.setFramePosition(0); // 从头开始播放
            backgroundMusic.start(); // 开始播放
            playMusicBtn.setEnabled(false);// 禁用播放按钮
            stopMusicBtn.setEnabled(true);// 启动停止按钮
        }
    }

    // 停止音乐
    private void stopMusic() {
        if (backgroundMusic != null) {
            backgroundMusic.stop();// 停止播放
            playMusicBtn.setEnabled(true);// 启动播放按钮
            stopMusicBtn.setEnabled(false);// 关闭停止按钮
        }
    }

    private java.awt.Color Color(int i, int j, int k) {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'Color'");
    }

    // 执行计算功能
    private void calculate() {
        // 获取文本框内容
        String expression = field.getText();
        // 如果表达式中有×和÷要替换为*和/
        expression = expression.replace("×", "*").replace("÷", "/");
        // 执行计算操作使用js计算引擎
        ScriptEngineManager manager = new ScriptEngineManager();
        // 初始化计算引擎 使用Javascript解析数学表达式
        ScriptEngine engine = manager.getEngineByName("javascript");
        try {
            // 开始计算 计算过程可能出现异常 这里处理异常
            Object result = engine.eval(expression);
            // 将结果显示到文本框
            field.setText(result.toString());
        } catch (ScriptException e) {
            // catch 中放的是异常处理方式
            e.printStackTrace();
        }
    }

    // 新增时间控制方法
    private void startTimeDisplay() {
        timeTimer.start();// 启动定时器
        isTimeDisplaying = true;
        btns[18].setText("■ 停止"); // 更新按钮文本
        field.setText(LocalTime.now().format(timeFormatter)); // 立即显示时间
    }

    private void stopTimeDisplay() {
        timeTimer.stop();// 关闭定时器
        isTimeDisplaying = false;
        btns[18].setText("T"); // 恢复按钮文本
        field.setText(""); // 清空文本框
    }

    private void setBtnText(String text) {
        String oldText = field.getText();

        // 当时间正在显示时，按其他按钮停止显示
        if (isTimeDisplaying && !text.equals("T")) {
            stopTimeDisplay();
        }

        switch (text) {
            case "C":
                // 清空列表
                // System.out.println("C");
                field.setText("");
                break;
            case "S":
                // 如果当前显示的是时间格式（包含:），则清空
                if (oldText.matches(".*\\d{2}:\\d{2}:\\d{2}.*")) {
                    field.setText("");
                }
                // double num = Double.parseDouble(oldText);
                // double x = num * num;
                // 显示结果
                // field.setText(String.valueOf(x));

                // System.out.println("result");
                break;
            case "B":
                // 获取输入框内容
                String numText = field.getText();
                // 输入框内容不为空
                if (numText.length() != 0) {
                    // 字符串长度-1
                    field.setText(numText.substring(0, numText.length() - 1));
                }
                // 删除最后一个字符
                // field.setText(oldText.substring(0, oldText.length() - 1));
                // System.out.println("B");
                break;
            case "T":
                if (!isTimeDisplaying) {
                    startTimeDisplay();
                } else {
                    stopTimeDisplay();
                }
                // field.setText(java.time.LocalTime.now().toString());
                // System.out.println("T");
                break;
            case "=":
                calculate();
                // System.out.println("=");
                break;
            default:
                // 获取当前文本框的内容
                String zfText = field.getText();
                // 如果文本框已经有内容
                if (zfText.length() > 0) {
                    // 获取最后一位
                    char lastChar = oldText.charAt(zfText.length() - 1);

                    // 如果当前输入是操作符
                    if ("+-×÷".contains(text)) {
                        // 如果上一个字符已经是操作符，则替换最后一个操作符
                        if ("+-×÷".indexOf(lastChar) != -1) {
                            field.setText(zfText.substring(0, zfText.length() - 1) + text);
                            return;
                        }
                        // 如果上一个字符是小数点，不允许直接跟操作符
                        if (lastChar == '.') {
                            return; // 忽略本次输入
                        }
                    }

                    // 如果当前输入是小数点
                    if (text.equals(".")) {
                        // 检查是否已经存在小数点（针对当前数字）
                        String[] parts = zfText.split("[+\\-×÷]");// 按操作符拆分，获取当前数字
                        if (parts.length > 0 && parts[parts.length - 1].contains(".")) {
                            return; // 当前数字已包含小数点，不再添加
                        }
                        // 如果前面没有数字，自动补0
                        if (zfText.length() == 0 || "+-×÷".indexOf(lastChar) != -1) {
                            field.setText(zfText + "0.");
                            return;
                        }
                    }
                } else {
                    // 第一个字符不能是操作符（除了减号）或小数点
                    if ("+×÷.".contains(text)) {
                        if (text.equals(".")) {
                            field.setText("0.");// 单独的小数点补0
                        }
                        return;
                    }
                }
                // System.out.println("setBtnText:" + text);
                // 按下数字键把文字放到输入框中

                field.setText(oldText + text);
                break;
        }

    }

    // 实现接口中的抽象方法 处理事件
    @Override
    public void actionPerformed(ActionEvent a) {
        // 此处可以捕获到ActionListener监听事件
        // System.out.println(a.getSource());
        // 获取被点击的按钮的文字
        Object source = a.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton) source;
            String text = btn.getText();
            // System.out.println(text);
            // 处理对应按键文字
            setBtnText(text);
        }
    }

    public static void main(String[] args) {
        // System.out.println("hello,Calculator");
        // 创建类的对象 - 线程不安全
        // new Calculator();
        // 是 Java Swing 开发中确保线程安全的核心代码
        SwingUtilities.invokeLater(Calculator::new);
    }
}